#pragma once
#include"TestLogger.h"
#include <iostream>
#include<time.h>
#include<string.h>
#include <stdarg.h>

using namespace lin::utility;

const char* Logger::s_level[LEVEL_COUNT] =
{
	"DEBUG",
	"INFO",
	"WARN",
	"ERROR",
	"FATAL"
};


Logger::Logger():m_max(0),m_len(0),m_level(Level::DEBUG)
{

}


Logger* Logger::m_instance = NULL;
Logger* Logger::instance()
{
	if (m_instance == NULL)
		m_instance = new Logger();
	return m_instance;
}

void Logger::log(Level level, const char* file, int line, const char* format, ...)
{
	if (m_level > level)
	{
		return;
	}

	if (m_fout.fail())
	{
		throw std::logic_error("打开日志文件失败:" + m_filename);
	}
	// 获取当前时间
	time_t ticks = time(NULL);
	struct tm* ptm = localtime(&ticks);
	char timestamp[32];
	memset(timestamp, 0, sizeof(timestamp));
	strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", ptm);

	char sumprintf[256];
	int len = 0;
	const char* fmt = "%s %s %s:%d";
	len = snprintf(NULL, 0, fmt, timestamp, s_level[level], file, line);
	if (len > 0)
	{
		char* buffer=new char[len+1];

		snprintf(sumprintf, len + 1, fmt, timestamp, s_level[level], file, line);
		snprintf(buffer, len + 1, fmt, timestamp, s_level[level], file, line);
		buffer[len] = 0;

		// 这里不知道为什么报错
		//strcat(sumprintf, buffer);
		//std::cout << sumprintf << std::endl;

		m_fout << buffer;
		
		delete[] buffer;
		
		m_len += len;  
	}

	va_list arg_ptr;
	va_start(arg_ptr, format);
	len = vsnprintf(NULL, 0, format, arg_ptr);
	va_end(arg_ptr);
	if (len > 0)
	{
		char* content = new char[len + 1];
		va_start(arg_ptr, format);
		vsnprintf(content, len + 1, format, arg_ptr);
		va_end(arg_ptr);
		content[len] = 0;
		m_fout << content;
		strcat(sumprintf, content);
		delete[] content;
		m_len += len;
	}
	std::cout << sumprintf << std::endl;
	// 换行
	m_fout << "\n";
	m_fout.flush();

	if (m_max > 0 && m_len >= m_max)
	{
		rotate();
	}
}
void Logger::rotate()
{
	close();
	time_t ticks = time(NULL);
	struct tm* ptm = localtime(&ticks);
	char timestamp[32];
	memset(timestamp, 0, sizeof(timestamp));
	strftime(timestamp, sizeof(timestamp), ".%Y-%m-%d_%H-%M-%S", ptm);
	string filename = m_filename + timestamp;
	if (rename(m_filename.c_str(), filename.c_str()) != 0)
	{
		throw std::logic_error("命名日志文件失败:" + string(strerror(errno)));
	}
	open(m_filename);
}

void Logger::close()
{
	m_fout.close();
}

void Logger::open(const string& filename)
{
	m_filename = filename;

	m_fout.open(filename.c_str(), ios::app);
	if (m_fout.fail())
	{
		throw std::logic_error("打开日志文件失败:" + filename);
	}
	m_fout.seekp(0, ios::end);
	m_len = m_fout.tellp();
}

void Logger::max(int bytes)
{
	m_max = bytes;
}

void Logger::level(int level)
{
	m_level = level;
}